#!/bin/sh
#
# $FreeBSD$
#

# PROVIDE: ix-ldap
# REQUIRE: root ix-ssl NETWORK
# BEFORE: SERVERS

. /etc/rc.freenas


LDAP_STATUS_ALERT="/tmp/.ldap_status_alert"

generate_ldapconf()
{
	LD_LIBRARY_PATH=/usr/local/lib /usr/local/bin/midclt call etc.generate ldap > /dev/null
}

generate_nss_ldapconf()
{
	rm -f /usr/local/etc/ldap.conf
	LD_LIBRARY_PATH=/usr/local/lib /usr/local/bin/midclt call etc.generate nss > /dev/null
	ln -sf /usr/local/etc/nss_ldap.conf /usr/local/etc/ldap.conf
}

get_cifs_homedir()
{
	${FREENAS_SQLITE_CMD} ${RO_FREENAS_CONFIG} "
	SELECT
		cifs_path

	FROM
		sharing_cifs_share

	WHERE
		cifs_home = 1

	ORDER BY
		-sharing_cifs_share.id

	LIMIT 1;
	"
}

setup_homedirs()
{
	# Stale symlinks and directories can make us sad.  This can happen
	# when you update the homedir path, or switch between LDAP and AD.

	local cifs_home="$(get_cifs_homedir)"

	# if /home is a dead symlink nuke it
	find /home -type l -maxdepth 0 -exec test ! -e {} \; -exec rm '{}' \;

	if [ -n "${cifs_home}" ] ; then
		# If /home is a directory nuke it
		if [ -d "/home" ]; then
			rmdir /home 2>/dev/null
			if  [ $? -ne 0 ]; then
				# rmdir has failed us, the directory must not be empty
				# In theory this should never happen, so we won't worry
				# about name collisions in our random new name.
				newhome="/home.$(dd if=/dev/random bs=4 count=1 2>/dev/null | /usr/local/bin/base64 | sed -e 's/[\/|=]//g')"
				mv /home ${newhome}
			fi
		fi
		# It's safe to create/update our symlink now
		ln -sfh "$cifs_home" "/home" 2>/dev/null

	else
		if [ -e "/home" ]; then
			if [ -d "/home" ]; then
				# Nothing to do here
			else
				# The only possibility here is /home is a file
				# or a valid symlink
				rm /home
				mkdir /home
			fi
		else
			# In theory this shouldn't be possible.  Dead symlinks get nuked
			# and working symlinks wouldn't get to this else clause
			if [ -L "/home" ]; then
				rm /home
			fi
			mkdir /home
		fi
	fi
}

ldap_status()
{
	local IFS=\|
	local ret=0
	local fail="/tmp/.ldap_fail"

	RO_FREENAS_CONFIG=$(ro_sqlite ${name} 2> /tmp/${name}.fail && rm /tmp/${name}.fail)
	trap 'rm -f ${RO_FREENAS_CONFIG}' EXIT

	${FREENAS_SQLITE_CMD} ${RO_FREENAS_CONFIG} "
	SELECT
		ldap.ldap_anonbind, 	 
		ldap.ldap_binddn, 	 
		ldap.ldap_bindpw, 	 
		ldap.ldap_ssl,
		kr.krb_realm,
		kp.principal_name
	FROM
		directoryservice_ldap as ldap

	LEFT OUTER JOIN
		directoryservice_kerberosrealm as kr
	ON
		ldap.ldap_kerberos_realm_id = kr.id

	LEFT OUTER JOIN
		directoryservice_kerberosprincipal as kp
	ON
		ldap.ldap_kerberos_principal_id = kp.id

	ORDER BY
		-ldap.id

	LIMIT 1
	" | \
	while eval read ldap_anonbind ldap_binddn ldap_bindpw ldap_ssl realm principal
	do
		local res=1
		local ldapsearch=/usr/local/bin/ldapsearch
		local options=

		if [ "${ldap_ssl}" = "start_tls" ]
		then
			options="-Z"
		fi

		if [ -n "${realm}" -a -n "${principal}" ]
		then
			local temp=$(mktemp /tmp/tmp.XXXXXX)
			local cmdfile=$(mktemp /tmp/tmp.XXXXXX)
			local cmd
		
			chmod 400 "${temp}"

			echo "${ldapsearch} ${options} -Y GSSAPI  -b '' -s base" > "${cmdfile}"
			cmd=$(cat ${cmdfile})
			eval "${cmd}" >/dev/null 2>&1
			res=$?

			rm -f "${temp}" "${cmdfile}"

		elif [ "${ldap_anonbind}" = "0" ]
		then
			local temp=$(mktemp /tmp/tmp.XXXXXX)
			local cmdfile=$(mktemp /tmp/tmp.XXXXXX)
			local cmd
		
			chmod 400 "${temp}"
			echo -n "$(/usr/local/bin/midclt call notifier.pwenc_decrypt ${ldap_bindpw})" > "${temp}"

			echo "${ldapsearch} ${options} -D '"${ldap_binddn}"' -b '' -s base -y "${temp}"" > "${cmdfile}"
			cmd=$(cat ${cmdfile})
			eval "${cmd}" >/dev/null 2>&1
			res=$?

			rm -f "${temp}" "${cmdfile}"
		else		
			local cmdfile=$(mktemp /tmp/tmp.XXXXXX)
			local cmd

			echo "${ldapsearch} -D '' -b '' -s base ${options}" > "${cmdfile}"
			cmd=$(cat ${cmdfile})
			eval "${cmd}" >/dev/null 2>&1
			res=$?

			rm -f "${cmdfile}"
		fi

		if [ "${res}" != "0" ]
		then
			touch "${fail}"
		fi
	done

	if [ -f "${fail}" ]
	then
		rm -f "${fail}"
		ret=1
	fi

	return ${ret}
}

ldap_start()
{
	if dirsrv_enabled ldap
	then
		RO_FREENAS_CONFIG=$(ro_sqlite ${name} 2> /tmp/${name}.fail && rm /tmp/${name}.fail)
		trap 'rm -f ${RO_FREENAS_CONFIG}' EXIT
		generate_nss_ldapconf

		if ! generate_ldapconf
		then
			touch $LDAP_STATUS_ALERT
			return 1
		fi

		if ! setup_homedirs
		then
			touch $LDAP_STATUS_ALERT
			return 2
		fi

		if ! create_cache_filesystem
		then
			return 4
		fi

		if ! ldap_status
		then
			touch $LDAP_STATUS_ALERT
		else
			rm -rf $LDAP_STATUS_ALERT
		fi
	fi
}

ldap_stop()
{
        /usr/local/www/freenasUI/tools/cachetool.py expire
}


name="ix-ldap"
start_cmd='ldap_start'
status_cmd='ldap_status'
stop_cmd='ldap_stop'
            
load_rc_config $name
run_rc_command "$1"
